package cn.wen.yaling.xo.service.impl;

import cn.wen.yaling.commons.constant.RedisConstants;
import cn.wen.yaling.commons.enums.TypeSort;
import cn.wen.yaling.commons.enums.TypeStatus;
import cn.wen.yaling.commons.service.RedisService;
import cn.wen.yaling.commons.utils.RedisUtils;
import cn.wen.yaling.commons.utils.ResultEntity;
import cn.wen.yaling.commons.vo.*;
import cn.wen.yaling.xo.dao.ArticleDao;
import cn.wen.yaling.xo.dao.SubjectDao;
import cn.wen.yaling.xo.service.CommentService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.wen.yaling.commons.utils.PageUtils;
import cn.wen.yaling.commons.utils.Query;

import cn.wen.yaling.xo.dao.TypeDao;
import cn.wen.yaling.commons.entity.TypeEntity;
import cn.wen.yaling.xo.service.TypeService;
import org.springframework.transaction.annotation.Transactional;


@Service("typeService")
public class TypeServiceImpl extends ServiceImpl<TypeDao, TypeEntity> implements TypeService {

    @Autowired
    private TypeDao typeDao;

    @Autowired
    private SubjectDao subjectDao;

    @Autowired
    private ArticleDao articleDao;

    @Autowired
    private CommentService commentService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<TypeEntity> page = this.page(
                new Query<TypeEntity>().getPage(params),
                new QueryWrapper<TypeEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<TypeVO> getTypeAllList() {
        // 每个分类增加了文章就需要删除缓存
        List<TypeVO> typeList;
        // 1、先判断redis缓存中是否能命中缓存
        if (redisService.hasKey(RedisConstants.CACHE_TYPE_ALL_LIST)) {
            typeList = redisUtils.getListCache(RedisConstants.CACHE_TYPE_ALL_LIST, TypeVO.class);
        } else {
            // 2、获取全部激活的问题列表  包括类别
            // 先获取全部的列表
            QueryWrapper<TypeEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("type_sort", 1);
            queryWrapper.eq("type_status", 1);
            List<TypeEntity> typeEntities = typeDao.selectList(queryWrapper);
            typeList = new ArrayList<>();
            for (TypeEntity typeEntity : typeEntities) {
                TypeVO typeVO = new TypeVO();
                // 获取每个分类下的数量
                Integer count = typeDao.getCountByTypeIdAndSort(typeEntity.getTypeId());
                BeanUtils.copyProperties(typeEntity, typeVO);
                typeVO.setArticleNum(count);
                typeList.add(typeVO);
            }
            // 3、将db中的缓存获取到
            redisUtils.setListCache(RedisConstants.CACHE_TYPE_ALL_LIST, typeList);
        }
        return typeList;
    }

    @Override
    public List<ArticleListVO> getTypeArticleList(Integer typeId) {
        List<ArticleListVO> articleList;
        // 1、先判断redis缓存中是否能命中缓存
        if (redisService.hasKey(RedisConstants.CACHE_TYPE_ARTICLE_LIST + ":" + "TA-" + typeId)) {
            articleList = redisUtils.getListCache(RedisConstants.CACHE_TYPE_ARTICLE_LIST + ":" + "TA-" + typeId, ArticleListVO.class);
        } else {
            // 2、获取全部激活的问题列表  包括类别
            articleList = articleDao.getTypeArticleList(typeId);
            // 3、将db中的缓存获取到
            redisUtils.setListCache(RedisConstants.CACHE_TYPE_ARTICLE_LIST + ":" + "TA-" + typeId, articleList);
        }
        for (ArticleListVO articleListVO : articleList) {
            articleListVO.setCommentNum(commentService.getCommentNumByArticleId(articleListVO.getArticleId()));
        }
        return articleList;
    }

    @Override
    public List<TypeEntity> getQuestionType() {
        QueryWrapper<TypeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type_sort", TypeSort.QUESTION.getStatus());
        queryWrapper.eq("type_status", TypeStatus.NORMAL_USE.getStatus());
        return typeDao.selectList(queryWrapper);
    }

    @Override
    public List<Map<String, Object>> getBlogCountByBlogSort() {
        List<TypeVO> typeAllList = getTypeAllList();
        List<Map<String, Object>> res = new ArrayList<>();
        for (TypeVO typeVO : typeAllList) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", typeVO.getTypeName());
            map.put("value", typeVO.getArticleNum().longValue());
            map.put("typeId", typeVO.getTypeId());
            res.add(map);
        }
        return res;
    }

    @Override
    public List<TypeEntity> getTypeList() {
        List<TypeEntity> typeList;
        String cacheKey = RedisConstants.CACHE_ADMIN_ALL_TYPE_LIST;
        // 1、先判断redis缓存中是否能命中缓存
        if (redisService.hasKey(cacheKey)) {
            typeList = redisUtils.getListCache(cacheKey, TypeEntity.class);
        } else {
            // 2、获取全部激活的问题列表  包括类别
            QueryWrapper<TypeEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.ne("type_status", TypeStatus.DELETED.getStatus());
            typeList = typeDao.selectList(queryWrapper);
            // 3、将db中的缓存获取到
            redisUtils.setListCache( cacheKey, typeList);
        }
        return typeList;
    }

    @Override
    public List<TypeEntity> searchType(String typeName) {
        QueryWrapper<TypeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("type_name", typeName);
        queryWrapper.ne("type_status", TypeStatus.DELETED.getStatus());
        return typeDao.selectList(queryWrapper);
    }

    @Transactional
    @Override
    public ResultEntity addType(TypeAddVO typeAddVO) {
        // 需要设置其他状态
        TypeEntity target = new TypeEntity();
        BeanUtils.copyProperties(typeAddVO, target);
        target.setCreateTime(new Date());
        target.setUpdateTime(new Date());
        target.setTypeStatus(TypeStatus.NORMAL_USE.getStatus());
        target.setTypeViewsNum(0);
        boolean res = typeDao.insert(target) > 0;
        // 插入
        if (!res) return ResultEntity.error();
        // 判断是否需要插入到 subjectType中
        if (target.getTypeSort() == TypeSort.SUBJECT_TYPE.getStatus()) {
            typeDao.insertSubjectType(target.getTypeId(), typeAddVO.getSubjectId());
            redisUtils.delSubjectArticleListCache(typeAddVO.getSubjectId());
        }
        // 删除缓存
        redisUtils.delTypeListCache();
        return ResultEntity.ok();
    }


    @Transactional
    @Override
    public ResultEntity deleteTypeByIds(Integer[] typeIds) {
        boolean res = typeDao.updateBatchTypeIds(typeIds, TypeStatus.DELETED.getStatus());
        if (!res) return ResultEntity.error();
        // 修改subjectTypeRelation的数据
        typeDao.deleteSubjectTypes(typeIds);
        redisUtils.delTypeListCache();
        return ResultEntity.ok();
    }

    @Override
    public ResultEntity updateTypeById(TypeUpdateVO type) {
        TypeEntity target = new TypeEntity();
        BeanUtils.copyProperties(type, target);
        target.setUpdateTime(new Date());
        boolean res = typeDao.updateById(target) > 0;
        if (!res) return ResultEntity.error();
        // 判断是否存在subjectId
        if (type.typeSort == TypeSort.SUBJECT_TYPE.getStatus()) {
            // 需要判断是添加还是
            // 校验是否需要删除
            if (typeDao.checkSubjectType(type.getTypeId()) != null) {
                // 存在则需要删除
                typeDao.deleteSubjectType(type.getTypeId());
            }
            // 插入
            typeDao.insertSubjectType(type.typeId, type.getSubjectId());
        } else {
            // 校验是否需要删除
            if (typeDao.checkSubjectType(type.getTypeId()) != null) {
                // 存在则需要删除
                typeDao.deleteSubjectType(type.getTypeId());
            }
        }
        redisUtils.delTypeListCache();
        if (type.getSubjectId() != null) {
            redisUtils.delSubjectArticleListCache(type.getSubjectId());
        }
        return ResultEntity.ok();
    }

    @Override
    public ResultEntity updateTypeStatusById(Integer typeId, Integer status) {
        TypeEntity target = new TypeEntity();
        target.setTypeId(typeId);
        target.setTypeStatus(status);
        boolean res =- typeDao.updateById(target) > 0;
        if (!res) return ResultEntity.error();
        redisUtils.delTypeListCache();
        return ResultEntity.ok();
    }

    @Override
    public ResultEntity getImageTypeListBySort() {
        QueryWrapper<TypeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type_status", TypeStatus.NORMAL_USE.getStatus());
        queryWrapper.eq("type_sort", TypeSort.IMAGE_TYPE.getStatus());
        List<TypeEntity> typeEntities = typeDao.selectList(queryWrapper);
        return ResultEntity.ok().put("data", typeEntities);
    }



}